package com.lastproject.web.bean;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.RequestScoped;
import javax.faces.bean.SessionScoped;
import javax.faces.component.UIComponent;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.event.ComponentSystemEvent;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;

import org.primefaces.event.FileUploadEvent;

import com.lastproject.dto.CandidateDTO;
import com.lastproject.dto.ConfidentialEmployeeDTO;
import com.lastproject.dto.InterviewDTO;
import com.lastproject.dto.UserDTO;
import com.lastproject.ejb.dao.CandidateDAORemote;
import com.lastproject.ejb.dao.CheckPermissionDAORemote;
import com.lastproject.ejb.dao.InterviewDAORemote;
import com.lastproject.ejb.dao.UserDAORemote;

@ManagedBean
@SessionScoped
public class CandidateBean implements Validator {
	private static final int DEFAULT_BUFFER_SIZE = 10240;

	// @ManagedProperty(value = "#{candidateDTO}")
	private CandidateDTO candidateDTO;

	// @ManagedProperty(value = "#{confidentialEmployeeDTO}")
	private ConfidentialEmployeeDTO confidentialEmployeeDTO;

	@EJB
	CandidateDAORemote candidateDAORemote;

	@EJB
	InterviewDAORemote interviewDAORemote;

	@EJB
	UserDAORemote userDAORemote;
	
	@EJB
	CheckPermissionDAORemote checkPermissionDAORemote;

	private String errorMess="";
	private String errorMessAdd="";
	private String errorMessDelete="";
	private String errorMessUpdate="";
	private String errorMessReject="";
	private boolean deletion = false;
	private int idCandidateForDeletion;
	private List<CandidateDTO> candidates;
	private List<InterviewDTO> interviews;
	private byte[] photo;
	
	public byte[] getPhoto() {
		return photo;
	}

	public void setPhoto(byte[] photo) {
		this.photo = photo;
	}
	
	public void preRenderView(ComponentSystemEvent event) {
        if (!checkPermissionDAORemote.hasCandidateManagementRights(true)){
        	FacesContext fc = FacesContext.getCurrentInstance();
        	ExternalContext ec = fc.getExternalContext();
        	try {
				ec.redirect("restrictedAccess.xhtml");
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
        }
    }
	
	public String startAddCandidate(){
		resetFields();
		return "addCandidate";
	}
	
	public void resetFields(){
		candidateDTO.setId(0);
		candidateDTO.setApplyingFor(null);
		candidateDTO.setBirthdate(null);
		candidateDTO.setCv(null);
		candidateDTO.setEmail(null);
		candidateDTO.setFirstname(null);
		candidateDTO.setLastname(null);
		candidateDTO.setDomain(null);
		
		errorMess="";
		errorMessAdd="";
		errorMessDelete="";
		errorMessUpdate="";
		errorMessReject="";
		
	}

	@PostConstruct
	public void init() {
		confidentialEmployeeDTO = new ConfidentialEmployeeDTO();
		candidateDTO = new CandidateDTO();
		candidates = candidateDAORemote.getAll();
		deletion = false;
		errorMess = "";
		// errorMessAdd = "";
		// errorMessDelete = "";
		// errorMessUpdate = "";
		// errorMessReject = "";
	}

	public boolean isDeletion() {
		return deletion;
	}

	public void setDeletion(boolean deletion) {
		this.deletion = deletion;
	}

	public int getIdCandidateForDeletion() {
		return idCandidateForDeletion;
	}

	public void setIdCandidateForDeletion(int idCandidate) {
		this.idCandidateForDeletion = idCandidate;
	}

	public String getErrorMessUpdate() {
		return errorMessUpdate;
	}

	public void setErrorMessUpdate(String errorMessUpdate) {
		this.errorMessUpdate = errorMessUpdate;
	}

	public String getErrorMess() {
		return errorMess;
	}

	public void setErrorMess(String errorMess) {
		this.errorMess = errorMess;
	}

	public String getErrorMessAdd() {
		return errorMessAdd;
	}

	public void setErrorMessAdd(String errorMessAdd) {
		this.errorMessAdd = errorMessAdd;
	}

	public String getErrorMessDelete() {
		return errorMessDelete;
	}

	public void setErrorMessDelete(String errorMessDelete) {
		this.errorMessDelete = errorMessDelete;
	}

	public String getErrorMessReject() {
		return errorMessReject;
	}

	public void setErrorMessReject(String errorMessReject) {
		this.errorMessReject = errorMessReject;
	}

	public List<CandidateDTO> getCandidates() {
		return candidates;
	}

	public void setCandidates(List<CandidateDTO> candidates) {
		this.candidates = candidates;
	}

	public CandidateDTO getCandidateDTO() {
		return candidateDTO;
	}

	public void setCandidateDTO(CandidateDTO candidateDTO) {
		this.candidateDTO = candidateDTO;
	}

	public ConfidentialEmployeeDTO getConfidentialEmployeeDTO() {
		return confidentialEmployeeDTO;
	}

	public void setConfidentialEmployeeDTO(
			ConfidentialEmployeeDTO confidentialEmployeeDTO) {
		this.confidentialEmployeeDTO = confidentialEmployeeDTO;
	}

	public void delete(int id) {
		deletion = true;
		idCandidateForDeletion = id;
	}

	/*
	 * delete candidate
	 */
	public String deleteCandidate() {
		candidateDTO = new CandidateDTO();

		candidateDTO = new CandidateDTO();
		candidateDTO = candidateDAORemote.findById(idCandidateForDeletion);

		interviews = interviewDAORemote
				.getListOfInterviewsByCandidate(candidateDTO.getId());

		deletion = false;
		if (interviews.isEmpty()) {

			if (candidateDTO.getStatut().equals("rejected")) {
				candidateDAORemote.remove(candidateDTO);
				init();
				return "listOfCandidates";
			} else {
				init();
				return errorMessDelete = "Only rejected candidates without interview appointment can be deleted.";
			}

		} else {
			init();
			return errorMessDelete = "Cannot delete candidate. He has an interview appointment.";
		}

	}

	public CandidateDTO findCandidateById(int id) {
		candidateDTO = candidateDAORemote.findById(id);
		return candidateDTO;
	}

	public String getCandidateForInterview() {
		String id = FacesContext.getCurrentInstance().getExternalContext()
				.getRequestParameterMap().get("id");
		System.out.println("ID: " + id);

		candidateDTO = candidateDAORemote.findById(Integer.parseInt(id));

		System.out.println("candidate name: " + candidateDTO.getFirstname());
		return "interview";
	}

	public String getCandidateForSendingEmail() {
		String id = FacesContext.getCurrentInstance().getExternalContext()
				.getRequestParameterMap().get("id");
		System.out.println("ID: " + id);

		candidateDTO = candidateDAORemote.findById(Integer.parseInt(id));

		return "sendEmailToCandidate";

	}
	
public void photoSave(FileUploadEvent event) throws ParseException {
		
		
		try {
			InputStream is = event.getFile().getInputstream();
			int i = is.available();
			byte[] b = new byte[i];

			is.read(b);
			System.out.println(is);
			if (b.length != 0) {
				photo = b;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		
		
	}

	public String createCandidate(ActionEvent actionEvent) throws IOException {

		try {

			FacesContext ctx = FacesContext.getCurrentInstance();
			ExternalContext ectx = ctx.getExternalContext();
			HttpServletRequest request = (HttpServletRequest) ectx.getRequest();

			InputStream is = request.getPart("upload:uploadFile")
					.getInputStream();
			int i = is.available();
			byte[] b = new byte[i];
			is.read(b);

			// Add candidate

			String firstname = (String) actionEvent.getComponent()
					.getAttributes().get("firstname");
			String lastname = (String) actionEvent.getComponent()
					.getAttributes().get("lastname");
			/*String email = (String) actionEvent.getComponent().getAttributes()
					.get("email");*/

			CandidateDTO cDTO = null;
			cDTO = candidateDAORemote.findByFullName(firstname, lastname);

			if (cDTO == null) {
				if(photo != null)
					candidateDTO.setPhoto(photo);
				photo = null;
				candidateDTO.setStatut("waiting");
				candidateDTO.setCv(b);

				candidateDAORemote.create(candidateDTO);

				errorMessAdd = "Candidate added succesfuly !";

				candidateDTO.setFirstname("");
				candidateDTO.setLastname("");
				candidateDTO.setBirthdate(null);
				candidateDTO.setApplyingFor("");
				candidateDTO.setDomain("");
				candidateDTO.setPhoneNr("");
				candidateDTO.setEmail("");

				deletion = false;

			} else {
				errorMessAdd = "Candidate already exists !";

			}

			init();
			return "addCandidate";

		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return null;
	}

	public void viewCv() throws IOException {

		deletion = false;

		FacesContext facesContext = FacesContext.getCurrentInstance();
		ExternalContext externalContext = facesContext.getExternalContext();
		HttpServletResponse response = (HttpServletResponse) externalContext
				.getResponse();
		HttpServletRequest request = (HttpServletRequest) externalContext
				.getRequest();
		String candidateId = request.getParameter("candidateId");
		BufferedInputStream input = null;
		BufferedOutputStream output = null;

		try {
			response.reset();
			response.setHeader("Content-Type", "application/pdf");
			output = new BufferedOutputStream(response.getOutputStream(),
					DEFAULT_BUFFER_SIZE);
			output.write(candidateDAORemote.findCv(Integer
					.parseInt(candidateId)));
			output.flush();

		} finally {
			close(output);
			close(input);
		}
		facesContext.responseComplete();
	}

	private static void close(Closeable resource) {

		if (resource != null) {
			try {
				resource.close();
			} catch (IOException e) {
				e.printStackTrace();

			}
		}
	}

	@Override
	public void validate(FacesContext context, UIComponent component,
			Object value) throws ValidatorException {

		List<FacesMessage> msgs = new ArrayList<FacesMessage>();
		Part file = (Part) value;
		errorMess = "";

		if (!"application/pdf".equals(file.getContentType())) {
			msgs.add(new FacesMessage("not a pdf"));
			errorMess = "Not a pdf";
		}
		if (!msgs.isEmpty()) {
			throw new ValidatorException(msgs);
		}

	}

	public String checkValues(ActionEvent actionEvent) {

		for (CandidateDTO candidateDTO : candidates) {

			if (candidateDTO.getFirstname().equals(""))
				return errorMess = "Empty firstname field!";
			if (candidateDTO.getLastname().equals(""))
				return errorMess = "Empty lastname field!";
			if (candidateDTO.getStatut().equals(""))
				return errorMess = "Empty statut field!";

			System.out.println("CANDIDATE: " + candidateDTO.getFirstname());

			candidateDAORemote.edit(candidateDTO);

			errorMess = "Update succesfuly !";

			init();
			deletion = false;
		}

		return null;

	}

	public String rejectCandidate() {
		String id = FacesContext.getCurrentInstance().getExternalContext()
				.getRequestParameterMap().get("id");

		System.out.println("ID candidat: " + id);

		UserDTO user = (UserDTO) FacesContext.getCurrentInstance()
				.getExternalContext().getSessionMap().get("userDTO");

		candidateDTO = candidateDAORemote.findById(Integer.parseInt(id));

		candidateDTO.setStatut("rejected");

		candidateDAORemote.edit(candidateDTO);

		// la sender tre sa fie mailul userului de pe sesiune
		interviewDAORemote
				.sendEmailToCandidate(user.getWorkEmail(),
						candidateDTO.getEmail(), "Rezultat interviu",
						"Ne pare rau, ati fost respins in urma interviului sustinut la firma noastra.");

		init();
		deletion = false;

		return "listOfCandidates";
	}

	public static String dateToString(Date date) {

		DateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd");

		String dateString = dateFormat.format(date);

		return dateString;

	}

	public String goBack() {
		init();
		errorMessAdd = "";
		errorMessDelete = "";
		errorMessUpdate = "";
		errorMessReject = "";
		return "listOfCandidates";
	}

	

}
